package com.zlyx.easy.security.defaults.provider;

import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.util.OAuth2Utils;

import com.zlyx.easy.core.utils.StringUtils;
import com.zlyx.easy.security.authentication.service.IUserDetailsService;
import com.zlyx.easy.security.authentication.token.AuthenticationToken;
import com.zlyx.easy.security.defaults.annoations.AuthorizationServer;
import com.zlyx.easy.security.defaults.annoations.EnableDefaultAuthorizationServer;

/**
 * <p>
 * 默认授权Provider
 * </p>
 *
 * @author 赵光
 * @version v1.0
 */
public class DefaultAuthenticationProvider implements AuthenticationProvider, InitializingBean {

	protected Logger logger = LoggerFactory.getLogger(SecurityConfigurerAdapter.class);

	protected List<String> grantTypes = Arrays
			.asList(System.getProperty(OAuth2Utils.GRANT_TYPE, EnableDefaultAuthorizationServer.DEFAULT_GRANT_TYPE));

	protected final GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();

	@Autowired
	protected IUserDetailsService userDetailsService;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		AuthenticationToken authenticationToken = (AuthenticationToken) authentication;
		if (authenticationToken == null) {
			throw new AuthenticationServiceException("authenticationToken is null");
		}
		if (!supports(authenticationToken)) {
			logger.debug("GrantType = {} is not support", authenticationToken.getGrantType());
			return null;
		}
		// 客户端id
		String clientId = authenticationToken.getClientId();
		Object principal = authenticationToken.getPrincipal();
		String username = loadUserName(clientId, principal);
		UserDetails userDetails = userDetailsService.loadUserByUsername(username);
		authenticationToken = new AuthenticationToken(userDetails, authenticationToken.getClientId(),
				authoritiesMapper.mapAuthorities(userDetails.getAuthorities()));
		authenticationToken.setDetails(authentication.getDetails());
		return authenticationToken;
	}

	/**
	 * 检验授权类型
	 * 
	 * @param authenticationToken authenticationToken
	 * @return
	 */
	public boolean supports(AuthenticationToken authenticationToken) {
		return grantTypes.contains(authenticationToken.getGrantType());
	}

	/**
	 * 获取用户id
	 * 
	 * @param clientId  客户端id
	 * @param principal 用户登录的唯一标识
	 * @return
	 */
	public String loadUserName(String clientId, Object principal) {
		return StringUtils.emptyOfNull(principal);
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return authentication.equals(AuthenticationToken.class);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		AuthorizationServer authorizationBean = this.getClass().getAnnotation(AuthorizationServer.class);
		if (authorizationBean != null) {
			grantTypes = Arrays.asList(authorizationBean.value());
		}
	}

}
